/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.web.approvalformat.core.service;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.inspur.edp.bcc.billcategory.entity.dimension.BillCategoryDimension;
import com.inspur.edp.bcc.billcategory.entity.dimension.inputtype.EnumInputInfo;
import com.inspur.edp.bcc.billcategory.entity.dimension.inputtype.EnumItem;
import com.inspur.edp.bcc.billcategory.entity.dimension.inputtype.InputType;
import com.inspur.edp.bcc.billcategory.entity.dimension.inputtype.SmartHelpInputInfo;
import com.inspur.edp.bcc.billcategory.entity.dimension.item.BillCatDimensionItem;
import com.inspur.edp.bef.api.lcp.ILcpFactory;
import com.inspur.edp.bef.api.lcp.IStandardLcp;
import com.inspur.edp.bef.api.services.IBefSessionManager;
import com.inspur.edp.cef.entity.condition.*;
import com.inspur.edp.cef.entity.condition.EntityFilter;
import com.inspur.edp.cef.entity.dependenceTemp.Pagination;
import com.inspur.edp.cef.entity.entity.IEntityData;
import com.inspur.edp.lcm.metadata.api.entity.GspMetadata;
import com.inspur.edp.lcm.metadata.api.entity.Metadata4Ref;
import com.inspur.edp.lcm.metadata.api.entity.MetadataHeader;
import com.inspur.edp.lcm.metadata.common.Utils;
import com.inspur.edp.metadata.businesstype.api.MdBizTypeMappingService;
import com.inspur.edp.metadata.rtcustomization.api.CustomizationService;
import com.inspur.edp.metadata.rtcustomization.api.entity.DimensionExtendEntity;
import com.inspur.edp.web.approvalformat.api.entity.*;
import com.inspur.edp.web.approvalformat.api.service.ApprovalFormMetadataService;
import com.inspur.edp.web.approvalformat.api.service.ApprovalFormatService;
import com.inspur.edp.web.approvalformat.api.service.DimensionService;
import com.inspur.edp.web.approvalformat.core.domain.converter.ApprovalFormatConverter;
import com.inspur.edp.web.approvalformat.core.domain.entity.ApprovalFormatDO;
import com.inspur.edp.web.approvalformat.core.domain.manager.ApprovalFormatManager;
import com.inspur.edp.web.approvalformat.core.util.*;
import com.inspur.edp.web.common.io.FileUtility;
import com.inspur.edp.web.common.logger.WebLogger;
import com.inspur.edp.web.common.utility.StringUtility;
import com.inspur.edp.web.help.api.LookupDataService;
import com.inspur.edp.web.help.api.LookupQueryParam;
import com.inspur.edp.web.help.api.LookupResult;
import com.inspur.edp.web.help.metadata.HelpMetadataContent;
import com.inspur.edp.web.jitruntimebuild.scriptcache.api.entity.ScriptCacheResponse;
import com.inspur.edp.web.jitruntimebuild.scriptcache.localserver.LocalServerVersionManager;
import io.iec.edp.caf.businessobject.api.entity.DevBasicBoInfo;
import io.iec.edp.caf.businessobject.api.service.DevBasicInfoService;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.rpc.api.service.RpcClient;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import com.inspur.edp.sgf.api.service.EapiRuntimeDeployment;
import com.inspur.edp.web.approvalformat.core.util.ApprovalFormatPermission;

import java.util.*;

/**
 * 维度服务
 *
 * @author Xu‘fa Wang
 * @date 2020/5/11 16:44
 */
public class ApprovalFormatServiceImpl implements ApprovalFormatService {
    private final static String FORM_TYPE = "form";

    private final MdBizTypeMappingService mdBizTypeMappingService = SpringBeanUtils.getBean(MdBizTypeMappingService.class);
    private final CustomizationService customizationService = SpringBeanUtils.getBean(CustomizationService.class);
    private final LookupDataService lookupDataService = SpringBeanUtils.getBean(LookupDataService.class);
    private final DevBasicInfoService devBasicInfoService = SpringBeanUtils.getBean(DevBasicInfoService.class);

    private DimensionService dimensionService = SpringBeanUtils.getBean(DimensionService.class);
    private final ApprovalFormMetadataService approvalFormMetadataService = SpringBeanUtils.getBean(ApprovalFormMetadataService.class);
    private ApprovalFormatManager approvalFormatManager = SpringBeanUtils.getBean(ApprovalFormatManager.class);
    private final EapiRuntimeDeployment eapiRuntimeDeployment = SpringBeanUtils.getBean(EapiRuntimeDeployment.class);

    public ApprovalFormatServiceImpl(DimensionService dimensionService, ApprovalFormatManager approvalFormatManager) {
        if (dimensionService != null) {
            this.dimensionService = dimensionService;
        }

        if (approvalFormatManager != null) {
            this.approvalFormatManager = approvalFormatManager;
        }
    }

    @Override
    public ApprovalFormatForestByDimension getApprovalFormatByDimension(String billCategoryId, String billCategoryExtendCode) {
        List<ApprovalFormatTreeNode> refList = getApprovalFormatForest(billCategoryId);
        BillCategoryDimension dList = this.dimensionService.getDimension(billCategoryId, billCategoryExtendCode);
        return new ApprovalFormatForestByDimension(refList, dList);
    }

    @Override
    public Map<String, Object> getEntityDataByBizEntityId(String dataId, String bizEntityId) {
        String targetServiceUnitCode = getServiceUnitCode(bizEntityId);
        if (targetServiceUnitCode == null || targetServiceUnitCode.isEmpty()) {
            throw new RuntimeException("当前BE对应su的编号为空。当前BE的id是：" + bizEntityId);
        }
        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        LinkedHashMap<String, Object> parameterHashMap = new LinkedHashMap<>();
        parameterHashMap.put("dataId", dataId);
        parameterHashMap.put("bizEntityId", bizEntityId);
        try {
            return (Map<String, Object>) client.invoke(Object.class,
                    "com.inspur.edp.web.approvalformat.rpc.rpcservice.IApprovalFormatRpcService.getEntityDataByBizEntityId",
                    targetServiceUnitCode,
                    parameterHashMap,
                    null);
        } catch (Exception e) {
            throw new RuntimeException("调用RPC服务发生异常。当前BE的id是：" + bizEntityId + ",获取到的su编号：" + targetServiceUnitCode, e);
        }
    }

    private String getServiceUnitCode(String metadataId) {
        GspMetadata bizEntityMetadata = this.customizationService.getMetadata(metadataId);
        if (bizEntityMetadata == null) {
            return null;
        }

        DevBasicBoInfo devBasicBoInfo = this.devBasicInfoService.getDevBasicBoInfo(bizEntityMetadata.getHeader().getBizobjectID());
        return devBasicBoInfo.getSuCode();
    }

    /**
     * 获取业务实体数据
     *
     * @param dataId            数据id
     * @param bizEntityConfigId 业务实体配置id
     * @return 指定数据id的实体数据对象
     */
    @Override
    public IEntityData getEntityDataByBizEntityConfigId(String dataId, String bizEntityConfigId) {
        SpringBeanUtils.getBean(IBefSessionManager.class).createSession();
        try {
            IStandardLcp lcp = SpringBeanUtils.getBean(ILcpFactory.class).createLcp(bizEntityConfigId);
            return lcp.retrieve(dataId).getData();
        } finally {
            SpringBeanUtils.getBean(IBefSessionManager.class).closeCurrentSession();
        }
    }

    @Override
    public List<IEntityData> queryEntityData(String bizEntityId) {
        String targetServiceUnitCode = getServiceUnitCode(bizEntityId);
        if (targetServiceUnitCode == null || targetServiceUnitCode.isEmpty()) {
            throw new RuntimeException("当前BE对应su的编号为空。当前BE的id是：" + bizEntityId);
        }

        LinkedHashMap<String, Object> parameterHashMap = new LinkedHashMap<>();
        parameterHashMap.put("bizEntityId", bizEntityId);

        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        try {
            return (List<IEntityData>) client.invoke(Object.class,
                    "com.inspur.edp.web.approvalformat.rpc.rpcservice.IApprovalFormatRpcService.queryEntityData",
                    targetServiceUnitCode,
                    parameterHashMap,
                    null);
        } catch (Exception e) {
            throw new RuntimeException("调用RPC服务发生异常。当前BE的id是：" + bizEntityId + ",获取到的su编号：" + targetServiceUnitCode + e.getMessage(), e);
        }
    }

    @Override
    public List<IEntityData> queryEntityDataWithCondition(JsonNode queryStringMap) {
        String bizEntityId = queryStringMap.get("bizEntityId").asText();
        String targetServiceUnitCode = getServiceUnitCode(bizEntityId);
        if (targetServiceUnitCode == null || targetServiceUnitCode.isEmpty()) {
            throw new RuntimeException("当前BE对应su的编号为空。当前BE的id是：" + bizEntityId);
        }

        LinkedHashMap<String, Object> parameterHashMap = new LinkedHashMap<>();
        parameterHashMap.put("queryStringMap", queryStringMap);

        RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
        try {
            return (List<IEntityData>) client.invoke(Object.class,
                    "com.inspur.edp.web.approvalformat.rpc.rpcservice.IApprovalFormatRpcService.queryEntityDataWithCondition",
                    targetServiceUnitCode,
                    parameterHashMap,
                    null);
        } catch (Exception e) {
            throw new RuntimeException("调用RPC服务发生异常。当前BE的id是：" + bizEntityId + ",获取到的su编号：" + targetServiceUnitCode + e.getMessage(), e);
        }
    }


    @Override
    public ApprovalFormatCreateResponseBody createApprovalFormat(ApprovalFormatCreateRequestBody approvalFormatCreateRequestBody) {
        new ApprovalFormatPermission().checkModulePermission();
        // 完整性检测
        if (checkIfExistsByBillCategoryIdAndDimension(approvalFormatCreateRequestBody.getBillCategoryId(),
                approvalFormatCreateRequestBody.getDim1(),
                approvalFormatCreateRequestBody.getDim2())) {
            throw new RuntimeException("不允许相同单据种类id下，存在两个维度定义相同的记录，请检查。");
        }


        // TODO: 相同元数据namespace + code + type 重复检测
        String formatCode = approvalFormatCreateRequestBody.getCode();
        try {
            ApprovalFormUtil.saveCheck(approvalFormatCreateRequestBody, "Form");
        } catch (Exception e) {
            throw new RuntimeException("已存在格式编号为" + formatCode + "的审批格式，请更换格式编号后重试。");
        }
        //todo 改为vo创建后，新增一个方法执行vo创建格式
        this.approvalFormMetadataService.createApprovalForm(approvalFormatCreateRequestBody);
        if (!isCreatedByViewModel(approvalFormatCreateRequestBody)) {
            this.approvalFormMetadataService.createApprovalFormViewObject(approvalFormatCreateRequestBody);
        } else {
            //不允许使用审批格式的VO创建新的审批格式
            if (checkIfExistsByViewModelId(approvalFormatCreateRequestBody.getVoId())) {
                throw new RuntimeException("当前视图对象已经创建过审批格式，不允许重复创建！");
            }
            //根据VO创建eapi元数据
            ApprovalFormUtil.deployManualVOandEapi(approvalFormatCreateRequestBody, approvalFormatCreateRequestBody.getVoId(), "");
        }

        ApprovalFormat approvalFormat = this.createApprovalFormatRelation(approvalFormatCreateRequestBody);

        return ApprovalFormatConverter.toCreateResponseBody(approvalFormat);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public ApprovalFormat createApprovalFormatRelation(ApprovalFormatCreateRequestBody approvalFormatCreateRequestBody) {
        ApprovalFormatDO relation = new ApprovalFormatDO();

        relation.setId(UUID.randomUUID().toString());
        relation.setBeId(approvalFormatCreateRequestBody.getBeId());
        relation.setDim1(approvalFormatCreateRequestBody.getDim1());
        relation.setDim2(approvalFormatCreateRequestBody.getDim2());
        relation.setFormId(approvalFormatCreateRequestBody.getFormId());
        relation.setVoId(approvalFormatCreateRequestBody.getVoId());
        relation.setFormUrl(approvalFormatCreateRequestBody.getFormUrl());
        relation.setBillCategoryId(approvalFormatCreateRequestBody.getBillCategoryId());

        DevBasicBoInfo devBasicBoInfo = this.devBasicInfoService.getDevBasicBoInfo(approvalFormatCreateRequestBody.getBizObjectId());
        String formUrl = createApprovalFormUrl(devBasicBoInfo.getAppCode().toLowerCase(), devBasicBoInfo.getSuCode().toLowerCase(), approvalFormatCreateRequestBody.getCode().toLowerCase());
        relation.setFormUrl(formUrl);

        return this.approvalFormatManager.add(relation);
    }

    @Override
    public void deleteApprovalFormat(String approvalFormatId) {
        // 基于id删除审批格式
        this.approvalFormatManager.deleteApprovalFormatById(approvalFormatId);
    }

    @Override
    public void deleteApprovalFormatAndRelation(String billCategoryId, String metadataId, String firstDimension, String secondDimension) {
        ApprovalFormat approvalFormat = getApprovalFormatByApprovalFormId(metadataId);
        if (approvalFormat == null) {
            return;
        }

        this.deleteApprovalFormatAndRelation(approvalFormat.getId(), billCategoryId, metadataId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRED)
    public void deleteApprovalFormatAndRelationById(String approvalFormatId) {
        ApprovalFormat approvalFormat = this.approvalFormatManager.getApprovalFormatById(approvalFormatId);
        if (approvalFormat == null) {
            return;
        }
        String billCategoryId = approvalFormat.getBillCategoryId();
        String approvalFormId = approvalFormat.getApprovalFormId();
        String approvalViewObjectId = approvalFormat.getViewObjectId();
        String bizEntityId = approvalFormat.getBizEntityId();
        //删除顺序 产物 - Form - Eapi - VO - 表记录

        // 删除审批格式相关产物
        // 删除预览审批格式之后产生的文件
        try {
            this.deleteFilesGeneratedInPreviewApprovalFormat(approvalFormId);
        } catch (Exception e) {
            throw new RuntimeException("删除移动审批相关文件失败。详细信息如下：" + e.getMessage());
        }

        //根据表单元数据获取Eapi的ID
        GspMetadata approvalFormMetaData = null;
        approvalFormMetaData = this.customizationService.getMetadata(approvalFormId);
        if (approvalFormMetaData == null) {
            throw new RuntimeException("获取审批格式失败");
        }
        // 删除审批单据
        this.customizationService.deleteGeneratedMetadata(approvalFormId);
        this.mdBizTypeMappingService.delete(billCategoryId, approvalFormId);
        ObjectNode voContent = ApprovalFormatUtil.getVoContent(approvalFormMetaData);
        String eapiId = voContent.get("eapiId").textValue();
        if (!StringUtility.isNullOrEmpty(eapiId)) {
            //取消部署Eapi元数据
            eapiRuntimeDeployment.removeDeploy(eapiId);
            //删除Eapi元数据
            this.customizationService.deleteGeneratedMetadata(eapiId);
        }

        //bizEntityId为空，代表是使用VO创建的审批格式
        if (!StringUtility.isNullOrEmpty(bizEntityId)) {
            // 删除审批单据VO，VO存在则调用删除方法
            GspMetadata approvalViewObjectMetadata = this.customizationService.getMetadata(approvalViewObjectId);
            if (approvalViewObjectMetadata != null) {
                this.customizationService.deleteGeneratedMetadata(approvalViewObjectId);
            }
            this.mdBizTypeMappingService.delete(billCategoryId, approvalViewObjectId);
        }
        // 删除审批格式
        this.approvalFormatManager.deleteApprovalFormatById(approvalFormatId);
    }

    @Override
    public ApprovalFormat updateApprovalFormat(ApprovalFormatUpdateRequestBody approvalFormatUpdateRequestBody) {
        if (!approvalFormatUpdateRequestBody.getApprovalFormatId().equals(approvalFormatUpdateRequestBody.getApprovalFormatInstance().getId())) {
            throw new RuntimeException("待更新审批格式id与待更新内容中id不一致，请检查。");
        }

        ApprovalFormat approvalFormatInstance = approvalFormatUpdateRequestBody.getApprovalFormatInstance();
        ApprovalFormat approvalFormatFromDatabase = this.approvalFormatManager.getApprovalFormatById(approvalFormatInstance.getId());
        if (approvalFormatFromDatabase == null) {
            throw new RuntimeException("待更新审批格式不存在，不能调用更新接口。请联系开发人员处理");
        }
        if (ApprovalFormatUtil.isEqual(approvalFormatInstance, approvalFormatFromDatabase)) {
            return approvalFormatInstance;
        }

        ApprovalFormatDO approvalFormatDO = ApprovalFormatConverter.toDo(approvalFormatInstance);
        if (this.approvalFormatManager.checkIfExistsByBillCategoryIdAndDimension(approvalFormatDO)) {
            throw new RuntimeException("不允许相同单据种类id下，存在两个维度定义相同的记录，请检查。");
        }

        return this.approvalFormatManager.save(approvalFormatDO);
    }

    @Override
    public ApprovalFormat updateApprovalFormatFormUrl(ApprovalFormatUpdateRequestBody approvalFormatUpdateRequestBody) {
        if (!approvalFormatUpdateRequestBody.getApprovalFormatId().equals(approvalFormatUpdateRequestBody.getApprovalFormatInstance().getId())) {
            throw new RuntimeException("待更新审批格式id与待更新内容中id不一致，请检查。");
        }

        ApprovalFormat approvalFormatInstance = approvalFormatUpdateRequestBody.getApprovalFormatInstance();
        ApprovalFormat approvalFormatFromDatabase = this.approvalFormatManager.getApprovalFormatById(approvalFormatInstance.getId());
        if (approvalFormatFromDatabase == null) {
            throw new RuntimeException("待更新审批格式不存在，不能调用更新接口。请联系开发人员处理");
        }
        // 检测到未修改，直接返回
        if (approvalFormatInstance.getApprovalFormPublishUri().equals(approvalFormatFromDatabase.getApprovalFormPublishUri())) {
            return approvalFormatInstance;
        }
        approvalFormatFromDatabase.setApprovalFormPublishUri(approvalFormatInstance.getApprovalFormPublishUri());
        ApprovalFormatDO approvalFormatDO = ApprovalFormatConverter.toDo(approvalFormatFromDatabase);
        return this.approvalFormatManager.save(approvalFormatDO);
    }


    @Override
    public ApprovalFormat updateApprovalFormatDimension(ApprovalFormatDimensionUpdateRequestBody approvalFormatDimensionUpdateRequestBody) {
        ApprovalFormat approvalFormatFromDatabase = this.approvalFormatManager.getApprovalFormatById(approvalFormatDimensionUpdateRequestBody.getId());
        if (approvalFormatFromDatabase == null) {
            throw new RuntimeException("待更新审批格式不存在，不能调用更新接口。请联系开发人员处理");
        }

        // 检测到未修改，直接返回
        if (approvalFormatFromDatabase.getFirstDimension().equals(approvalFormatDimensionUpdateRequestBody.getFirstDimension())
                && approvalFormatFromDatabase.getSecondDimension().equals(approvalFormatDimensionUpdateRequestBody.getSecondDimension())) {
            return approvalFormatFromDatabase;
        }
        approvalFormatFromDatabase.setFirstDimension(approvalFormatDimensionUpdateRequestBody.getFirstDimension());
        approvalFormatFromDatabase.setSecondDimension(approvalFormatDimensionUpdateRequestBody.getSecondDimension());

        ApprovalFormatUpdateRequestBody approvalFormatUpdateRequestBody = new ApprovalFormatUpdateRequestBody();
        approvalFormatUpdateRequestBody.setApprovalFormatId(approvalFormatDimensionUpdateRequestBody.getId());
        approvalFormatUpdateRequestBody.setApprovalFormatInstance(approvalFormatFromDatabase);

        return updateApprovalFormat(approvalFormatUpdateRequestBody);
    }

    @Override
    public ApprovalFormat getApprovalFormatEntityById(String approvalFormatId) {
        return getApprovalFormatByApprovalFormId(approvalFormatId);
    }

    @Override
    public List<ApprovalFormat> getApprovalFormatCollection(String billCategoryId) {
        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBillCategoryId(billCategoryId);

        updateApprovalFormatCodeAndName(approvalFormatCollection);

        return approvalFormatCollection;
    }

    @Override
    public List<ApprovalFormat> getApprovalFormatCollectionOrderByDimension(String billCategoryId) {
        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBillCategoryIdAndOrderByDimension(billCategoryId);

        updateApprovalFormatCodeAndName(approvalFormatCollection);

        return approvalFormatCollection;
    }

    @Override
    public List<ApprovalFormatQueryResponseBody> getApprovalFormatCollectionOrderByDimension(String billCategoryId, String billCategoryExtendCode) {
        return createApprovalFormatQueryResponseBody(billCategoryId, billCategoryExtendCode);
    }

    @Override
    public void replicateApprovalFormat(String approvalFormatId) {

    }

    @Override
    public ApprovalFormat getApprovalFormatByBizEntityIdWithDimension(String businessEntityId, String firstDimension, String secondDimension) {
        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBeIdWithFirstDimensionAndSecondDimension(businessEntityId, firstDimension, secondDimension);
        if (approvalFormatCollection == null || approvalFormatCollection.size() <= 0) {
            return null;
        }
        if (approvalFormatCollection.size() > 1) {
            throw new RuntimeException("表中存在重复数据，请联系开发人员处理。");
        }

        return approvalFormatCollection.get(0);
    }

    @Override
    public ApprovalFormat getApprovalFormatByBillCategoryIdWithDimension(String billCategoryId, String firstDimension, String secondDimension) {
        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBillCategoryIdWithFirstDimensionAndSecondDimension(billCategoryId, firstDimension, secondDimension);
        if (approvalFormatCollection == null || approvalFormatCollection.size() <= 0) {
            return null;
        }
        if (approvalFormatCollection.size() > 1) {
            throw new RuntimeException("表中存在重复数据，请联系开发人员处理。");
        }

        return approvalFormatCollection.get(0);
    }

    @Override
    public String getApprovalFormUri(String businessEntityId, String firstDimension, String secondDimension) {
        ApprovalFormat approvalFormat = getApprovalFormatByBizEntityIdWithDimension(businessEntityId, firstDimension, secondDimension);
        if (approvalFormat == null) {
            return null;
        } else {
            //从数据库取出移动审批js的content，放到publish目录
            if (!StringUtility.isNullOrEmpty(approvalFormat.getApprovalFormId())) {
                ScriptCacheResponse scriptCacheResponse = LocalServerVersionManager.getSingleInstance().checkVersionWithFormMetadataId(approvalFormat.getApprovalFormId());
            }
        }
        return approvalFormat.getApprovalFormPublishUri();
    }

    @Override
    public String getApprovalFormUriByBillCategoryId(String billCategory, String firstDimension, String secondDimension) {
        //new ApprovalFormatPermission().checkModulePermission();
        ApprovalFormat approvalFormat = getApprovalFormatByBillCategoryIdWithDimension(billCategory, firstDimension, secondDimension);
        if (approvalFormat == null) {
            return null;
        }
        return approvalFormat.getApprovalFormPublishUri();
    }

    @Override
    public HelpProviderResult getHelpProviderData(String billCategoryId, String billCategoryExtendCode, String dimensionId, String billCategoryDimensionItemId) {
        SpringBeanUtils.getBean(IBefSessionManager.class).createSession();

        try {
            BillCategoryDimension billCategoryDimension = this.dimensionService.getDimension(billCategoryId, billCategoryExtendCode);
            if (billCategoryDimension == null) {
                return null;
            }

            List<BillCatDimensionItem> billCategoryDimensionItemList = billCategoryDimension.getDimensionItems();
            if (billCategoryDimensionItemList == null || billCategoryDimensionItemList.size() <= 0) {
                return null;
            }
            for (BillCatDimensionItem billCategoryDimensionItem : billCategoryDimensionItemList) {
                if (billCategoryDimensionItem.getDimensionId().equals(dimensionId) && billCategoryDimensionItem.getId().equals(billCategoryDimensionItemId)) {
                    InputType inputType = billCategoryDimensionItem.getInputInfo().getInputType();
                    if (inputType == InputType.SmartHelpInput) {
                        SmartHelpInputInfo smartHelpInputInfo = (SmartHelpInputInfo) billCategoryDimensionItem.getInputInfo();
                        String helperId = smartHelpInputInfo.getHelperId();

                        HelpMetadataContent helpMetadataContent = (HelpMetadataContent) this.customizationService.getMetadata(helperId).getContent();
                        HelpMetadataSimpleContent helpMetadataSimpleContent = HelpProviderUtil.convertToHelpMetadataSimpleContent(helpMetadataContent);

                        HelpProviderResult helpProviderResult = new HelpProviderResult();
                        helpProviderResult.setHelpMetadataSimpleContent(helpMetadataSimpleContent);
                        helpProviderResult.setLookupResult(this.lookupDataService.getData(helperId, new LookupQueryParam()));

                        return helpProviderResult;
                    }
                }
            }

            return null;
        } finally {
            SpringBeanUtils.getBean(IBefSessionManager.class).closeCurrentSession();
        }
    }

    private List<ApprovalFormatTreeNode> getApprovalFormatForest(String billCategoryId) {
        List<ApprovalFormatTreeNode> treeList = new ArrayList<>();

        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBillCategoryId(billCategoryId);
        HashMap<String, ApprovalFormat> formIdApprovalFormatMap = new HashMap<>(16);
        for (ApprovalFormat approvalFormat : approvalFormatCollection) {
            String currentFormId = approvalFormat.getApprovalFormId();
            if (formIdApprovalFormatMap.containsKey(currentFormId)) {
                throw new RuntimeException("审批格式和审批单据的一对一映射被破坏，请联系开发人员处理。审批单据id是：" + approvalFormat.getApprovalFormId());
            }
            formIdApprovalFormatMap.put(currentFormId, approvalFormat);
        }

        List<Metadata4Ref> matadataList = this.mdBizTypeMappingService.getMetadataListByBizTypeId(billCategoryId, Collections.singletonList(FORM_TYPE));
        if (matadataList == null || matadataList.size() <= 0) {
            return treeList;
        }

        List<DimensionExtendEntity> children;
        MetadataHeader metadataHeader;
        ApprovalFormat approvalFormat;
        ApprovalFormatTreeNode treeNode;
        for (Metadata4Ref approvalFormMetadataRef : matadataList) {
            metadataHeader = approvalFormMetadataRef.getMetadata().getHeader();
            approvalFormat = formIdApprovalFormatMap.get(metadataHeader.getId());
            try {
                children = this.customizationService.getMetadataInfoRecusively(metadataHeader.getId(), metadataHeader.getCertId());
            } catch (Exception e) {
                throw new RuntimeException("getMetadataInfoRecusively Error.");
            }

            if (children != null && children.size() > 0) {

                treeNode = ApprovalFormatTreeUtil.assembleTree(ApprovalFormatTreeUtil.convertToApprovalFormat(metadataHeader, approvalFormat, "", "", true),
                        ApprovalFormatTreeUtil.groupByDimensions(ApprovalFormatTreeUtil.convertToRtcTemplateList(children, formIdApprovalFormatMap)));
                treeList.add(treeNode);
            } else {
                treeList.add(new ApprovalFormatTreeNode(ApprovalFormatTreeUtil.convertToApprovalFormat(metadataHeader, approvalFormat, "", "", true), new ArrayList<>()));
            }
        }
        return treeList;
    }

    private ApprovalFormat getApprovalFormatByApprovalFormId(String approvalFormId) {
        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByFormId(approvalFormId);
        if (approvalFormatCollection == null || approvalFormatCollection.size() <= 0) {
            return null;
        }
        if (approvalFormatCollection.size() > 1) {
            throw new RuntimeException("表中存在重复数据，请联系开发人员处理。");
        }

        return approvalFormatCollection.get(0);
    }

    private boolean checkIfExistsByBillCategoryIdAndDimension(String billCategoryId, String firstDimension, String secondDimension) {
        ApprovalFormat approvalFormatInstance = new ApprovalFormat();
        approvalFormatInstance.setBillCategoryId(billCategoryId);
        approvalFormatInstance.setFirstDimension(firstDimension);
        approvalFormatInstance.setSecondDimension(secondDimension);

        ApprovalFormatDO approvalFormatDO = ApprovalFormatConverter.toDo(approvalFormatInstance);
        return this.approvalFormatManager.checkIfExistsByBillCategoryIdAndDimension(approvalFormatDO);
    }

    /**
     * VO创建审批格式专用
     *
     * @param viewModelId 视图对象编号
     * @return
     */
    private boolean checkIfExistsByViewModelId(String viewModelId) {
        ApprovalFormat approvalFormatInstance = new ApprovalFormat();
        approvalFormatInstance.setViewObjectId(viewModelId);
        ApprovalFormatDO approvalFormatDO = ApprovalFormatConverter.toDo(approvalFormatInstance);
        return this.approvalFormatManager.checkIfExistsByViewModelId(approvalFormatDO);
    }

    private String createApprovalFormUrl(String applicationCode, String serviceUnitCode, String approvalFormCode) {
        String formUrl = "/" + "apps" + "/"
                + applicationCode.toLowerCase() + "/"
                + serviceUnitCode.toLowerCase() + "/"
                + "mobileapproval" + "/"
                + approvalFormCode.toLowerCase() + "/"
                + approvalFormCode.toLowerCase() + ".js";

        return formUrl;
    }

    private void deleteApprovalFormatAndRelation(String approvalFormatId, String billCategoryId, String metadataId) {
        if (metadataId == null || metadataId.isEmpty()) {
            return;
        }

        this.customizationService.deleteExtMetadata(metadataId, "");

//        // 检查是否存在维度
//        boolean firstDimensionIsNullOrEmpty = firstDimension == null || firstDimension.isEmpty();
//        boolean secondDimensionIsNullOrEmpty = secondDimension == null || secondDimension.isEmpty();
//        if(firstDimensionIsNullOrEmpty && secondDimensionIsNullOrEmpty) {
        this.mdBizTypeMappingService.delete(billCategoryId, metadataId);
//        }

        if (approvalFormatId == null || approvalFormatId.isEmpty()) {
            return;
        }
        this.approvalFormatManager.deleteApprovalFormatById(approvalFormatId);
    }


    /**
     * 删除审批设计时文件
     *
     * @param formId 审批表单id
     * @throws Exception
     */
    private void deleteFilesGeneratedInPreviewApprovalFormat(String formId) throws Exception {
        if (formId == null || formId.isEmpty()) {
            throw new Exception("删除移动审批相关文件失败,表单编号为空。");
        }

        GspMetadata gspMetadata = ApproveFormatPreviewUtil.getGspMetadataWithFormId(formId);
        String formCode = gspMetadata.getHeader().getCode();
        String mobileApproveAppPath = ApproveFormatPreviewUtil.generateMobileApproveDevBasePath(formCode);
        try {
            FileUtility.deleteFolder(mobileApproveAppPath);
        } catch (Exception e) {
            WebLogger.Instance.error(e);
        }
    }

    private void updateApprovalFormatCodeAndName(List<ApprovalFormat> approvalFormatCollection) {
        if (approvalFormatCollection == null || approvalFormatCollection.size() <= 0) {
            return;
        }

        for (ApprovalFormat approvalFormat : approvalFormatCollection) {
            GspMetadata approvalForm = this.customizationService.getMetadata(approvalFormat.getApprovalFormId());
            if (approvalForm == null) {
                throw new RuntimeException("获取元数据失败。待获取元数据ID是：" + approvalFormat.getApprovalFormId());
            }
            MetadataHeader approvalFormMetadataHeader = approvalForm.getHeader();
            approvalFormat.setCode(approvalFormMetadataHeader.getCode());
            approvalFormat.setName(approvalFormMetadataHeader.getName());
        }
    }

    private List<ApprovalFormatQueryResponseBody> createApprovalFormatQueryResponseBody(String billCategoryId, String billCategoryExtendCode) {
        new ApprovalFormatPermission().checkModulePermission();
        List<ApprovalFormatQueryResponseBody> approvalFormatQueryResponseBodyList = new LinkedList<>();

        List<ApprovalFormat> approvalFormatCollection = this.approvalFormatManager.getApprovalFormatByBillCategoryIdAndOrderByDimension(billCategoryId);
        if (approvalFormatCollection == null || approvalFormatCollection.size() <= 0) {
            return approvalFormatQueryResponseBodyList;
        }

        BillCategoryDimension billCategoryDimension = this.dimensionService.getDimension(billCategoryId, billCategoryExtendCode);
        List<BillCatDimensionItem> billCategoryDimensionCollection = null;
        if (billCategoryDimension != null) {
            billCategoryDimensionCollection = billCategoryDimension.getDimensionItems();
        }
        Map<String, List<Object>> helpProviderCache = new HashMap<>(2);

        List<String> firstDimensionIds = new ArrayList<>();
        List<String> secondDimensionIds = new ArrayList<>();

        for (ApprovalFormat approvalFormat : approvalFormatCollection) {
            if(StringUtils.isNotBlank(approvalFormat.getFirstDimension())){
                firstDimensionIds.add(approvalFormat.getFirstDimension());
            }
            if(StringUtils.isNotBlank(approvalFormat.getSecondDimension())){
                secondDimensionIds.add(approvalFormat.getSecondDimension());
            }
        }

        for (ApprovalFormat approvalFormat : approvalFormatCollection) {
            ApprovalFormatQueryResponseBody approvalFormatQueryResponseBody = ApprovalFormatUtil.convertToApprovalFormatQueryResponseBody(approvalFormat);
            GspMetadata approvalForm = this.customizationService.getMetadata(approvalFormatQueryResponseBody.getApprovalFormId());
            if (approvalForm == null) {
                throw new RuntimeException("获取元数据失败。待获取元数据ID是：" + approvalFormatQueryResponseBody.getApprovalFormId());
            }
            MetadataHeader approvalFormMetadataHeader = approvalForm.getHeader();
            approvalFormatQueryResponseBody.setCode(approvalFormMetadataHeader.getCode());
            approvalFormatQueryResponseBody.setName(approvalFormMetadataHeader.getName());

            // 更新第一维度和第二维度(将code更新成name)
            if (billCategoryDimensionCollection == null) {
                approvalFormatQueryResponseBodyList.add(approvalFormatQueryResponseBody);
                continue;
            }
            if (billCategoryDimensionCollection.size() > 0) {
                int dim = 0;
                for (BillCatDimensionItem billCatDimensionItem : billCategoryDimensionCollection) {
                    dim = dim + 1;

                    InputType inputType = billCatDimensionItem.getInputInfo().getInputType();
                    if (inputType == InputType.SmartHelpInput) {
                        SmartHelpInputInfo smartHelpInputInfo = (SmartHelpInputInfo) billCatDimensionItem.getInputInfo();
                        String helperId = smartHelpInputInfo.getHelperId();
                        HelpMetadataContent helpMetadataContent = null;
                        LookupResult lookupResult = null;
                        List<Object> helpProvider = helpProviderCache.get(helperId);
                        if (helpProvider == null) {
                            SpringBeanUtils.getBean(IBefSessionManager.class).createSession();
                            try {
                                helpMetadataContent = (HelpMetadataContent) this.customizationService.getMetadata(helperId).getContent();
                                LookupQueryParam lookupQueryParam = new LookupQueryParam();
                                EntityFilter entityFilter = new EntityFilter();
                                ArrayList<FilterCondition> filterConditionList = new ArrayList<>();
                                FilterCondition filterCondition_ids = new FilterCondition(0,helpMetadataContent.getIdField(), ExpressCompareType.In,"",0, ExpressRelationType.Empty, ExpressValueType.Value);
                                if(dim == 1){
                                    filterCondition_ids.setInValues(firstDimensionIds);
                                }
                                if(dim == 2){
                                    filterCondition_ids.setInValues(secondDimensionIds);
                                }
                                filterConditionList.add(filterCondition_ids);
                                entityFilter.setFilterConditions(filterConditionList);
                                lookupQueryParam.setFilter(entityFilter);
                                lookupResult = this.lookupDataService.getData(helperId, lookupQueryParam);
                                helpProvider = new ArrayList<>();
                                helpProvider.add(0, helpMetadataContent);
                                helpProvider.add(1, lookupResult);
                                helpProviderCache.put(helperId, helpProvider);
                            } finally {
                                SpringBeanUtils.getBean(IBefSessionManager.class).closeCurrentSession();
                            }
                        } else {
                            helpMetadataContent = (HelpMetadataContent) helpProvider.get(0);
                            lookupResult = (LookupResult) helpProvider.get(1);
                        }
                        String textFieldCode = helpMetadataContent.getTextField();
                        String idFieldCode = helpMetadataContent.getIdField();

                        Object itemCollectionObject = lookupResult.getItems();
                        JsonNode itemCollectionJsonNode = getJsonNode(itemCollectionObject);

                        for (JsonNode itemJsonNode : itemCollectionJsonNode) {
                            // treeList类型帮助
                            // 遍历helpId
                            if ("TreeList".equals(lookupResult.getDisplayType()) || "NavListTree".equals(lookupResult.getDisplayType())) {
                                do {
                                    JsonNode dataJsonNode = itemJsonNode.get("data");
                                    while (dataJsonNode != null) {
                                        tryToUpdateApprovalFormatQueryResponseBodyDimension(dataJsonNode, idFieldCode, textFieldCode, approvalFormatQueryResponseBody);
                                        if (itemJsonNode.get("children") != null && itemJsonNode.get("children").isArray() && itemJsonNode.get("children").size() > 0) {
                                            for (int i = 0; i < itemJsonNode.get("children").size(); i++) {
                                                dataJsonNode = itemJsonNode.get("children").get(i).get("data");
                                                tryToUpdateApprovalFormatQueryResponseBodyDimension(dataJsonNode, idFieldCode, textFieldCode, approvalFormatQueryResponseBody);

                                                if (itemJsonNode.get("children").get(i).get("children") != null && itemJsonNode.get("children").get(i).get("children").isArray() && itemJsonNode.get("children").get(i).get("children").size() > 0) {
                                                    for (int j = 0; j < itemJsonNode.get("children").get(i).get("children").size(); j++) {
                                                        JsonNode childDataJsonNode = itemJsonNode.get("children").get(i).get("children").get(j).get("data");
                                                        tryToUpdateApprovalFormatQueryResponseBodyDimension(childDataJsonNode, idFieldCode, textFieldCode, approvalFormatQueryResponseBody);
                                                    }
                                                }

                                            }
                                            if (itemJsonNode.elements().hasNext()) {
                                                itemJsonNode = itemJsonNode.elements().next();
                                                dataJsonNode = itemJsonNode.get("data");
                                            }
                                        } else {
                                            dataJsonNode = null;
                                        }
                                    }
                                    itemJsonNode = itemJsonNode.elements().next();
                                } while (itemJsonNode.elements().hasNext());
                            }
                            // list类型帮助
                            if ("List".equals(lookupResult.getDisplayType()) || "NavTreeList".equals(lookupResult.getDisplayType())  || "NavList".equals(lookupResult.getDisplayType()) ) {
                                tryToUpdateApprovalFormatQueryResponseBodyDimension(itemJsonNode, idFieldCode, textFieldCode, approvalFormatQueryResponseBody);
                            }
                        }
                    } else if (inputType == InputType.EnumInput) {
                        EnumInputInfo enumInputInfo = (EnumInputInfo) billCatDimensionItem.getInputInfo();
                        for (EnumItem enumItem : enumInputInfo.getEnumItems()) {
                            if (enumItem.getKey().equals(approvalFormatQueryResponseBody.getFirstDimension())) {
                                approvalFormatQueryResponseBody.setFirstDimensionName(enumItem.getValue());
                            }
                            if (enumItem.getKey().equals(approvalFormatQueryResponseBody.getSecondDimension())) {
                                approvalFormatQueryResponseBody.setSecondDimensionName(enumItem.getValue());
                            }
                        }
                    }
                }
            }

            approvalFormatQueryResponseBodyList.add(approvalFormatQueryResponseBody);
        }

        return approvalFormatQueryResponseBodyList;
    }

    private void tryToUpdateApprovalFormatQueryResponseBodyDimension(JsonNode dataJsonNode, String idFieldCode, String textFieldCode, ApprovalFormatQueryResponseBody approvalFormatQueryResponseBody) {
        if (dataJsonNode != null && dataJsonNode.get(idFieldCode) != null && dataJsonNode.get(textFieldCode) != null) {
            if (dataJsonNode.get(idFieldCode).asText().equals(approvalFormatQueryResponseBody.getFirstDimension())) {
                // JsonNode转换成String
                approvalFormatQueryResponseBody.setFirstDimensionName(dataJsonNode.get(textFieldCode).asText());
            }
            if (dataJsonNode.get(idFieldCode).asText().equals(approvalFormatQueryResponseBody.getSecondDimension())) {
                approvalFormatQueryResponseBody.setSecondDimensionName(dataJsonNode.get(textFieldCode).asText());
            }
        }
    }

    private JsonNode getJsonNode(Object objectInstance) {
        try {
            ObjectMapper mapper = Utils.getMapper();
            String itemCollectionObjectStr = mapper.writeValueAsString(objectInstance);

            return mapper.readTree(itemCollectionObjectStr);

        } catch (JsonProcessingException e) {
            WebLogger.Instance.error(e);
            throw new RuntimeException(e);
        }
    }

    private boolean isCreatedByViewModel(ApprovalFormatCreateRequestBody approvalFormatCreateRequestBody) {
        if (approvalFormatCreateRequestBody == null) {
            throw new RuntimeException("参数为空，请检查!");
        }
        return StringUtility.isNullOrEmpty(approvalFormatCreateRequestBody.getBeId());

    }

    private String checkVersionWithApprovalFormat(ApprovalFormat approvalFormat) {
        if (!StringUtility.isNullOrEmpty(approvalFormat.getBizEntityId())) {
            //String targetServiceUnitCode = getServiceUnitCode(approvalFormat.getBizEntityId());
            String targetServiceUnitCode = "bcc";
            if (targetServiceUnitCode == null || targetServiceUnitCode.isEmpty()) {
                throw new RuntimeException("当前BE对应su的编号为空。当前BE的id是：" + approvalFormat.getBizEntityId());
            }
            RpcClient client = SpringBeanUtils.getBean(RpcClient.class);
            LinkedHashMap<String, Object> parameterHashMap = new LinkedHashMap<>();
            parameterHashMap.put("formMetadataId", approvalFormat.getApprovalFormId());
            try {
                return (String) client.invoke(Object.class,
                        "com.inspur.edp.web.jitruntimebuild.scriptcache.localserver.rpc.LocalServerVersionRpcService.checkVersionWithFormMetadataId",
                        targetServiceUnitCode,
                        parameterHashMap,
                        null);
            } catch (Exception e) {
                throw new RuntimeException("调用RPC服务发生异常。当前BE的id是：" + approvalFormat.getBizEntityId() + ",传递的su编号：" + targetServiceUnitCode, e);
            }
        }
        return "";
    }

}
